package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTemplateEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.FieldPermissionEntityExt;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateNodeEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.ProcessOpinionEnum;
import com.xbongbong.paas.enums.ProcessSaasFormEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.model.PaasProcessTemplateNodeModel;
import com.xbongbong.paas.pojo.ProcessFieldAttrPojo;
import com.xbongbong.paas.pojo.ProcessVersionPojo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.FormGetDTO;
import com.xbongbong.paas.pojo.dto.NeedApproveDTO;
import com.xbongbong.paas.pojo.dto.NewProcessNodeDTO;
import com.xbongbong.paas.pojo.dto.ProcessArchiveDTO;
import com.xbongbong.paas.pojo.dto.ProcessDeleteDTO;
import com.xbongbong.paas.pojo.dto.ProcessEnableDTO;
import com.xbongbong.paas.pojo.dto.ProcessGetDTO;
import com.xbongbong.paas.pojo.dto.ProcessOpenDTO;
import com.xbongbong.paas.pojo.dto.ProcessOpenDistributorDTO;
import com.xbongbong.paas.pojo.dto.ProcessParamsDTO;
import com.xbongbong.paas.pojo.dto.ProcessPreviewDTO;
import com.xbongbong.paas.pojo.dto.ProcessTaskCountDTO;
import com.xbongbong.paas.pojo.dto.ProcessTemplateAddDTO;
import com.xbongbong.paas.pojo.dto.ProcessTemplateNodeUpdateDTO;
import com.xbongbong.paas.pojo.dto.ProcessTemplateUpdateDTO;
import com.xbongbong.paas.pojo.dto.ProcessUpdateDTO;
import com.xbongbong.paas.pojo.dto.ProcessVersionDTO;
import com.xbongbong.paas.pojo.vo.FormEntityGetVO;
import com.xbongbong.paas.pojo.vo.NeedApprovePojo;
import com.xbongbong.paas.pojo.vo.NeedApproveVO;
import com.xbongbong.paas.pojo.vo.ProcessArchiveVO;
import com.xbongbong.paas.pojo.vo.ProcessDeleteVO;
import com.xbongbong.paas.pojo.vo.ProcessEnableVO;
import com.xbongbong.paas.pojo.vo.ProcessFormFieldVO;
import com.xbongbong.paas.pojo.vo.ProcessGetVO;
import com.xbongbong.paas.pojo.vo.ProcessOpenVO;
import com.xbongbong.paas.pojo.vo.ProcessParamsVO;
import com.xbongbong.paas.pojo.vo.ProcessTaskCountVO;
import com.xbongbong.paas.pojo.vo.ProcessTreeVO;
import com.xbongbong.paas.pojo.vo.ProcessUpdateVO;
import com.xbongbong.paas.pojo.vo.ProcessVersionVO;
import com.xbongbong.paas.service.PaasProcessTemplateNodeService;
import com.xbongbong.paas.service.PaasProcessTemplateService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.DynamicManagerLevelEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ApprovalErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.script.pojo.dto.ProcessDTO;
import com.xbongbong.process.task.PaasProcessTaskService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.DefaultDistributorProcessEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.base.PaymentSheetBaseEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.CostAdjustEnum;
import com.xbongbong.saas.enums.business.CreditFixedLimitEnum;
import com.xbongbong.saas.enums.business.CreditTemporaryLimitEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InvoiceEnum;
import com.xbongbong.saas.enums.business.OrderOutStockEnum;
import com.xbongbong.saas.enums.business.OtherExpenseEnum;
import com.xbongbong.saas.enums.business.OtherIncomeEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.ReceiptOrderEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.enums.business.WorkOrderOutstockEnum;
import com.xbongbong.saas.enums.product.BusinessProductCompareEnum;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.RoleEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.RoleModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Description: 流程设计操作服务层实现
 *
 * @author 李杰
 * @version v1.0
 * @date 2019/1/15 14:35
 * @since v1.0
 */
@Service("paasProcessDesignService")
public class PaasProcessTemplateServiceImpl implements PaasProcessTemplateService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasProcessTemplateServiceImpl.class);
    @Resource
    private PaasProcessTaskService paasProcessTaskService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasProcessTemplateModel processTemplateModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private PaasProcessTemplateNodeService processTemplateNodeService;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private PaasProcessTemplateNodeModel paasProcessTemplateNodeModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private RoleModel roleModel;

    /**
     * 开启流程
     *
     * @param processOpenDTO
     * @return ProcessOpenVO
     * @throws XbbException 表单不存在  流程已开启
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProcessOpenVO open(ProcessOpenDTO processOpenDTO) throws XbbException {
        ProcessOpenVO processOpenVO = new ProcessOpenVO();
        Integer saasMark = processOpenDTO.getSaasMark();
        Integer businessType = processOpenDTO.getBusinessType();
        try {
            if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                if (!ProcessSaasFormEnum.containsBusinessType(businessType) || (Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(), businessType) && Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), processOpenDTO.getDistributorMark()))) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.BUSINESS_TYPE_NOT_EXIST);
                }
            }
            //
            Map<String, Object> map = BeanUtil.convertBean2Map(processOpenDTO, true);
            List<PaasProcessTemplateEntityExt> templateList = processTemplateModel.list(map);
            if (!templateList.isEmpty()) {
                String userId = processOpenDTO.getUserId();
                Long formId = processOpenDTO.getFormId();
                String userName = processOpenDTO.getLoginUserName();
                // 将表单主表更新为流程表单
                PaasFormEntity paasFormEntity = new PaasFormEntity();
                BeanUtil.copyProperties(processOpenDTO, paasFormEntity, true);
                paasFormEntity.setId(formId);
                updateFormType(paasFormEntity, 1, MenuTypeEnum.PROCESS_FORM.getType(), userId, userName, processOpenDTO.getHttpHeader());
            } else {
                // 如果表单下没有流程的话，则新建流程；
                processOpenVO = createProcess(processOpenDTO);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库开启流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processOpenVO;
    }

    /**
     * 删除流程
     *
     * @param processDeleteDTO
     * @return ProcessDeleteVO
     * @throws XbbException 数据库异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProcessDeleteVO delete(ProcessDeleteDTO processDeleteDTO) throws XbbException {
        ProcessDeleteVO processDeleteVO = new ProcessDeleteVO();
        String corpId = processDeleteDTO.getCorpid();
        Long formId = processDeleteDTO.getFormId();
        String userId = processDeleteDTO.getUserId();
        String userName = processDeleteDTO.getLoginUserName();
        PaasProcessTemplateEntity paasProcessTemplateEntity = new PaasProcessTemplateEntity();

        try {
            // 有没有历史审批数据
            ProcessTaskCountDTO processTaskCountDTO = new ProcessTaskCountDTO();
            BeanUtil.copyProperties(processDeleteDTO, processTaskCountDTO);
            processTaskCountDTO.setTemplateId(processDeleteDTO.getProcessTemplateId());
            ProcessTaskCountVO processTaskCountVO = paasProcessTaskService.count(processTaskCountDTO);
            if (processTaskCountVO.getCount() != 0) {
                throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209008, ApprovalErrorCodeEnum.API_ERROR_209008.getMsg());
            }
            // 有没有其他模板，没有就更新表单实体
            Map<String, Object> params = BeanUtil.convertBean2Map(processDeleteDTO, true);
            Integer count = paasProcessTemplateModel.getEntitysCount(params);
            if (count == 1) {
                PaasFormEntity paasFormEntity = new PaasFormEntity();
                BeanUtil.copyProperties(processDeleteDTO, paasFormEntity);
                paasFormEntity.setId(formId);
                // 将流程表单改为普通表单
                updateFormType(paasFormEntity, 0, MenuTypeEnum.FORM.getType(), userId, userName, processDeleteDTO.getHttpHeader());
            }

            // 删除流程模板
            BeanUtils.copyProperties(processDeleteDTO, paasProcessTemplateEntity);
            paasProcessTemplateEntity.setId(processDeleteDTO.getProcessTemplateId());
            processTemplateModel.delete(paasProcessTemplateEntity);
            // TODO 需要关联删除流程节点
            // 获取流程节点
            params.put("templateId", processDeleteDTO.getProcessTemplateId());
            List<PaasProcessTemplateNodeEntityExt> processNodeList = paasProcessTemplateNodeModel.list(params);
            paasProcessTemplateNodeModel.deleteBatch(processNodeList,corpId);
            BeanUtil.copyProperties(processDeleteDTO, processDeleteVO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库删除流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // 记录日志
        String formName = null;
        if (Objects.equals(paasProcessTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpId);
            if (workOrderEntity != null) {
                formName = workOrderEntity.getName();
            }
        } else {
            PaasFormEntityExt formEntity = paasFormModel.getByKey(formId, corpId);
            if (formEntity != null) {
                formName = formEntity.getName();
            }
        }
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_PROCESS_TEMPLATE), userName, formName);
        mongoLogHelp.buildLog(corpId, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                OperateTypeEnum.DELETE, formId.toString(), formName, memo, processDeleteDTO.getHttpHeader());

        return processDeleteVO;
    }

    /**
     * 获取流程
     *
     * @param processGetDTO
     * @return ProcessGetVO
     * @throws XbbException 流程或节点或流转条件不存在、表单解释不存在
     */
    @Override
    public ProcessGetVO get(ProcessGetDTO processGetDTO) throws XbbException {
        ProcessGetVO processGetVO = new ProcessGetVO();
        try {
            // 获取流程模板
            Long templateId = processGetDTO.getProcessTemplateId();
            PaasProcessTemplateEntityExt templateEntityExt = processTemplateModel.getByKey(templateId, processGetDTO.getCorpid());
            if (templateEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NOT_EXIST);
            }
            BeanUtil.copyProperties(templateEntityExt, processGetVO);
            if (templateEntityExt.getVersionId() == null) {
                templateEntityExt.setVersionId(1);
            }
            if (templateEntityExt.getAutomaticallyApprovedSponsor() == null){
                templateEntityExt.setAutomaticallyApprovedSponsor(0);
            }
            if(templateEntityExt.getApproverDeduplication() == null ){
                templateEntityExt.setApproverDeduplication(3);
            }
            processGetVO.setProcessTemplate(templateEntityExt);
            // 获取流程节点
            Map<String, Object> params = BeanUtil.convertBean2Map(processGetDTO, true);
            params.put("templateId", templateId);
            params.put("orderByStr", " priority " + SortOrder.ASC);
            List<PaasProcessTemplateNodeEntityExt> processNodeList = paasProcessTemplateNodeModel.list(params);
            getProcessTree(processGetDTO, processGetVO, templateEntityExt, processNodeList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库获取流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processGetVO;
    }

    /**
     * 获取流程
     *
     * @param processPreviewDTO
     * @return ProcessGetVO
     * @throws XbbException 流程或节点或流转条件不存在、表单解释不存在
     */
    @Override
    public ProcessGetVO processPreview(ProcessPreviewDTO processPreviewDTO) throws XbbException {
        ProcessGetVO processGetVO = new ProcessGetVO();
        try {
            // 获取流程模板
            Map<String, Object> params = BeanUtil.convertBean2Map(processPreviewDTO, true);
            params.put("orderByStr", " version_id " + SortOrder.ASC);
            List<PaasProcessTemplateEntityExt> processList = processTemplateModel.list(params);
            if (processList.isEmpty()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NOT_EXIST);
            }
            PaasProcessTemplateEntityExt templateEntityExt = null;
            for (int i = 0; i < processList.size(); i++) {
                PaasProcessTemplateEntityExt template = processList.get(i);
                if (Objects.equals(template.getEnable(), 1)) {
                    templateEntityExt = template;
                    break;
                }
                if (i == processList.size() - 1 && Objects.isNull(templateEntityExt)) {
                    templateEntityExt = processList.get(0);
                }
            }
            BeanUtil.copyProperties(templateEntityExt, processGetVO);
            if (templateEntityExt.getVersionId() == null) {
                templateEntityExt.setVersionId(1);
            }
            processGetVO.setProcessTemplate(templateEntityExt);
            // 获取流程节点
            params.put("templateId", templateEntityExt.getId());
            params.put("orderByStr", " priority " + SortOrder.ASC);
            List<PaasProcessTemplateNodeEntityExt> processNodeList = paasProcessTemplateNodeModel.list(params);
            ProcessGetDTO processGetDTO = new ProcessGetDTO();
            BeanUtil.copyProperties(processPreviewDTO, processGetDTO);
            processGetDTO.setProcessTemplateId(templateEntityExt.getId());
            getProcessTree(processGetDTO, processGetVO, templateEntityExt, processNodeList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库获取流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processGetVO;
    }

    private void getProcessTree(ProcessGetDTO processGetDTO, ProcessGetVO processGetVO, PaasProcessTemplateEntityExt templateEntityExt, List<PaasProcessTemplateNodeEntityExt> processNodeList) throws XbbException {
        String explains;
        Integer versionType = processGetDTO.getVersionType();
        if (Objects.equals(processGetDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(processGetDTO.getFormId(), processGetDTO.getCorpid());
            if (workOrderExplainEntityExt == null) {
                throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209012, ApprovalErrorCodeEnum.API_ERROR_209012.getMsg());
            } else {
                explains = workOrderExplainEntityExt.getExplains();
            }
        } else {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(processGetDTO.getFormId(), processGetDTO.getCorpid());
            if (paasFormExplainEntity == null) {
                throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209012, ApprovalErrorCodeEnum.API_ERROR_209012.getMsg());
            } else {
                explains = paasFormExplainEntity.getExplains();
            }
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(explains, FieldAttrEntity.class);
        if (Objects.equals(templateEntityExt.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
            removeSaasHiddenField(processNodeList, explainList);
        }
        addNewFieldPermission(processNodeList, explainList);
        formatFieldPermissionMap(processNodeList);
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains, null);
        List<String> needApproveFieldList = templateEntityExt.getNeedApproveFieldList();
        // 删除需审批字段中表单已删除的字段
        if (needApproveFieldList != null) {
            removeDelFieldList(needApproveFieldList, explainMap);
        }
        if (Objects.equals(templateEntityExt.getType(), 2)) {
            List<ProcessTreeVO> processTreeVOList = new ArrayList<>();

            Set<String> userIds = processNodeList.stream()
                    .filter(v -> !Objects.equals(v.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType()))
                    .map(v -> {
                        List<OptionalRangeEntity> l = new ArrayList<>();
                        l.addAll(v.getMainUserList());
                        l.addAll(v.getCcUserList());
                        l.addAll(v.getTransferUserList());
                        return l;
                    }).flatMap(v -> v.stream())
                    .filter(v -> Objects.equals(v.getProperty(), OptionalRangeEnum.USER.getValue()))
                    .map(OptionalRangeEntity::getId)
                    .collect(Collectors.toSet());

            Map<String, String> userIdMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(userIds)) {
                List<UserEntity> userEntities = userModel.getByUserIdIn(processGetDTO.getCorpid(), userIds);
                userIdMap = userEntities.stream().collect(Collectors.toMap(v -> v.getUserId().toString(), UserEntity::getName));
            }

            Set<Long> depIds = processNodeList.stream()
                    .filter(v -> !Objects.equals(v.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType()))
                    .map(v -> {
                        List<OptionalRangeEntity> l = new ArrayList<>();
                        l.addAll(v.getMainUserList());
                        l.addAll(v.getCcUserList());
                        l.addAll(v.getTransferUserList());
                        return l;
                    }).flatMap(v -> v.stream())
                    .filter(v -> Objects.equals(v.getProperty(), OptionalRangeEnum.DEPT.getValue()))
                    .map(v -> Long.valueOf(v.getId()))
                    .collect(Collectors.toSet());
            Map<String, String> depMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(depIds)) {
                List<DepartmentEntity> departmentEntities = departmentModel.getByDepIdIn(processGetDTO.getCorpid(), depIds);
                depMap = departmentEntities.stream().collect(Collectors.toMap(v -> v.getId().toString(), DepartmentEntity::getName));
            }

            Set<Integer> roleIds = processNodeList.stream()
                    .filter(v -> !Objects.equals(v.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType()))
                    .map(v -> {
                        List<OptionalRangeEntity> l = new ArrayList<>();
                        l.addAll(v.getMainUserList());
                        l.addAll(v.getCcUserList());
                        l.addAll(v.getTransferUserList());
                        return l;
                    }).flatMap(v -> v.stream())
                    .filter(v -> Objects.equals(v.getProperty(), OptionalRangeEnum.ROLE.getValue()))
                    .map(v -> Integer.valueOf(v.getId()))
                    .collect(Collectors.toSet());
            Map<String, String> roleMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(depIds)) {
                List<RoleEntity> roleEntities = roleModel.getByRoleIdIn(processGetDTO.getCorpid(), roleIds);
                roleMap = roleEntities.stream().collect(Collectors.toMap(v -> v.getId().toString(), RoleEntity::getRoleName));
            }


            for (PaasProcessTemplateNodeEntityExt templateNodeEntityExt : processNodeList) {
                ProcessTreeVO processTreeVO = new ProcessTreeVO();
                if (Objects.equals(templateNodeEntityExt.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType())) {
                    List<ConditionsEntityExt> resultConditionList = getConditionsEntityExtList(explainMap, templateNodeEntityExt.getConditions());
                    templateNodeEntityExt.setConditionByClass(resultConditionList);
                }

                // 负责人转换为新的动态负责人
                transformDynamic(templateNodeEntityExt, userIdMap, depMap, roleMap);
                // 前端要给历史版本节点一个标识
                if (Objects.equals(versionType, BasicConstant.THREE)){
                    processTreeVO.setIsHistory(1);
                }
                processTreeVO.setName(templateNodeEntityExt.getName());
                processTreeVO.setNodeId(templateNodeEntityExt.getUid());
                processTreeVO.setPrevId(templateNodeEntityExt.getPrevId());
                processTreeVO.setType(templateNodeEntityExt.getType());
                processTreeVO.setPriority(templateNodeEntityExt.getPriority());
                processTreeVO.setData(JSONObject.parseObject(JSONObject.toJSONString(templateNodeEntityExt)));
                processTreeVOList.add(processTreeVO);
            }
            ProcessTreeVO processTreeVO = buildTree(processTreeVOList);
            processGetVO.setProcessTree(processTreeVO);
        } else {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private void formatFieldPermissionMap(List<PaasProcessTemplateNodeEntityExt> processNodeList) {
        for (PaasProcessTemplateNodeEntityExt item : processNodeList) {
            List<FieldPermissionEntityExt> filedPermissionList = item.getFieldPermissionList();
            Map<String, FieldPermissionEntityExt> fieldPermissionMap = new HashMap<>(filedPermissionList.size());
            filedPermissionList.forEach(fieldPermissionEntityExt -> {
                FieldPermissionEntityExt fieldPermissionEntity = new FieldPermissionEntityExt();
                BeanUtil.copyProperties(fieldPermissionEntityExt, fieldPermissionEntity);
                if (StringUtil.isNotEmpty(fieldPermissionEntityExt.getSubAttr())) {
                    fieldPermissionMap.put(fieldPermissionEntityExt.getAttr() + "." + fieldPermissionEntityExt.getSubAttr(), fieldPermissionEntity);
                } else {
                    fieldPermissionMap.put(fieldPermissionEntityExt.getAttr(), fieldPermissionEntity);
                }
            });
            item.setFieldPermissionMap(fieldPermissionMap);
            // 这两个前端都不要，去掉
            item.getFieldPermissionList().clear();
            item.setFieldPermission("");
        }

    }

    private void removeDelFieldList(List<String> needApproveFieldList, Map<String, FieldAttrEntity> explainMap) {
        Iterator<String> iterator = needApproveFieldList.iterator();
        while (iterator.hasNext()) {
            String field = iterator.next();
            if (!explainMap.containsKey(field)) {
                iterator.remove();
            } else {
                FieldAttrEntity fieldAttrEntity = explainMap.get(field);
                if (Objects.equals(fieldAttrEntity.getIsOpen(), 0)) {
                    iterator.remove();
                }
            }
        }
    }

    // 小鲍加的，bug我不管
    private void addNewFieldPermission(List<PaasProcessTemplateNodeEntityExt> processNodeList, List<FieldAttrEntity> explainList) {
        Set<String> fieldAttr = new HashSet<>(explainList.size());
        explainList.forEach(item -> {
            if (Objects.equals(item.getFieldType(), FieldTypeEnum.SUB_FORM.getType())
                    || Objects.equals(item.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())) {
                fieldAttr.add(item.getAttr());
                List<? extends FieldAttrEntity> subExplainList = item.getSubForm().getItems();
                subExplainList.forEach(subExplain -> {
                    fieldAttr.add(item.getAttr() + "_" + subExplain.getAttr());
                });
            } else {
                fieldAttr.add(item.getAttr());
            }
        });
        for (PaasProcessTemplateNodeEntityExt item : processNodeList) {
            List<FieldPermissionEntityExt> filedPermissionList = item.getFieldPermissionList();
            Set<String> filedPermission = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 1.移除表单中删掉的解释 2.构建filedPermission
            Iterator<FieldPermissionEntityExt> iterator = filedPermissionList.iterator();
            while (iterator.hasNext()) {
                FieldPermissionEntityExt fieldPermissionEntityExt = iterator.next();
                String permission = fieldPermissionEntityExt.getAttr();
                if (StringUtil.isNotEmpty(fieldPermissionEntityExt.getSubAttr())) {
                    permission += "_" + fieldPermissionEntityExt.getSubAttr();
                }
                if (!fieldAttr.contains(permission)) {
                    iterator.remove();
                    continue;
                }
                filedPermission.add(permission);
            }

            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (Objects.equals(fieldAttrEntity.getIsRedundant(), 1)) {
                    if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())
                            || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())) {
                        if (!filedPermission.contains(fieldAttrEntity.getAttr())) {
                            filedPermissionList.add(new FieldPermissionEntityExt(fieldAttrEntity.getAttr(), fieldAttrEntity.getFieldType(), 0, 0, 0));
                        }
                        List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                        subExplainList.forEach(subExplain -> {
                            if (!filedPermission.contains(fieldAttrEntity.getAttr() + "_" + subExplain.getAttr())) {
                                filedPermissionList.add(new FieldPermissionEntityExt(fieldAttrEntity.getAttr(), subExplain.getAttr(), fieldAttrEntity.getFieldType(), 0, 0, 0));
                            }
                        });
                    } else {
                        if (!filedPermission.contains(fieldAttrEntity.getAttr())) {
                            filedPermissionList.add(new FieldPermissionEntityExt(fieldAttrEntity.getAttr(), fieldAttrEntity.getFieldType(), 0, 0, 0));
                        }
                    }
                } else if (Objects.equals(fieldAttrEntity.getIsRedundant(), 0) && Objects.equals(fieldAttrEntity.getEditHide(), 0)) {
                    if (!filedPermission.contains(fieldAttrEntity.getAttr())) {
                        if ((Objects.equals(fieldAttrEntity.getSetType(), 1) || Objects.equals(fieldAttrEntity.getSetType(), 2))) {
                            filedPermissionList.add(new FieldPermissionEntityExt(fieldAttrEntity.getAttr(), fieldAttrEntity.getFieldType(), fieldAttrEntity.getEditable(), fieldAttrEntity.getVisible(), 0));
                        } else {
                            filedPermissionList.add(new FieldPermissionEntityExt(fieldAttrEntity.getAttr(), fieldAttrEntity.getFieldType(), 0, 0, 0));
                        }

                    }
                }
            }
        }
    }

    private Map<String, FieldAttrEntity> getExplainMap(NeedApproveDTO needApproveDTO, Long formId, String corpid, Integer businessType) throws XbbException {
        Map<String, FieldAttrEntity> explainMap;
        if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(formId, corpid);
            if (workOrderExplainEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            explainMap = ExplainUtil.getExplainMap(workOrderExplainEntityExt.getExplains(), null);
        } else if (Objects.equals(businessType, XbbRefTypeEnum.CREDIT_TEMPORARY_LIMIT.getCode()) || Objects.equals(businessType, XbbRefTypeEnum.CREDIT_FIXED_LIMIT.getCode())) {
            // 临时额度和固定额度不支持编辑进审批，去掉字段
            explainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        } else {
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if (paasFormExplainEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            needApproveDTO.setDistributorMark(paasFormExplainEntity.getDistributorMark());
            explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        }
        return explainMap;
    }

    private List<ConditionsEntityExt> getConditionsEntityExtList(Map<String, FieldAttrEntity> explainMap, List<ConditionsEntityExt> conditions) {
        List<ConditionsEntityExt> resultConditionList = new ArrayList<>();
        for (ConditionsEntityExt condition : conditions) {
            ConditionsEntityExt resultCondition = new ConditionsEntityExt();
            BeanUtil.copyProperties(condition, resultCondition);
            FieldAttrEntity fieldAttrEntity = explainMap.get(condition.getAttr());
            if (Objects.equals(condition.getAttr(), FieldTypeEnum.CREATORID.getAlias())) {
                if (explainMap.containsKey(condition.getAttr())) {
                    resultCondition.setName(explainMap.get(condition.getAttr()).getAttrName());
                } else {
                    resultCondition.setName(I18nMessageUtil.getMessage(CommonConstant.CREATOR));
                }
                resultConditionList.add(resultCondition);
                continue;
            } else if (Objects.equals(condition.getAttr(), FieldTypeEnum.ADDTIME.getAlias())) {
                if (explainMap.containsKey(condition.getAttr())) {
                    resultCondition.setName(explainMap.get(condition.getAttr()).getAttrName());
                } else {
                    resultCondition.setName(I18nMessageUtil.getMessage(CommonConstant.CREATE_TIME));
                }
                resultConditionList.add(resultCondition);
                continue;
            } else if (Objects.equals(condition.getAttr(), FieldTypeEnum.UPDATETIME.getAlias())) {
                if (explainMap.containsKey(condition.getAttr())) {
                    resultCondition.setName(explainMap.get(condition.getAttr()).getAttrName());
                } else {
                    resultCondition.setName(I18nMessageUtil.getMessage(CommonConstant.UPDATE_TIME));
                }
                resultConditionList.add(resultCondition);
                continue;
            } else if (Objects.equals(condition.getAttr(), FieldTypeEnum.CREATOR_DEPT.getAlias())) {
                resultCondition.setName(I18nMessageUtil.getMessage(I18nStringConstant.SPONSOR_DEPARTMENT));
                resultConditionList.add(resultCondition);
                continue;
            }
            if (fieldAttrEntity != null) {
                resultCondition.setName(fieldAttrEntity.getAttrName());
                // 对子表单数据格式化处理
                if (StringUtil.isNotEmpty(condition.getSubAttr())) {
                    List<? extends FieldAttrEntity> jsonArray = explainMap.get(condition.getAttr()).getSubForm().getItems();
                    resultCondition.setSubName(condition.getName() + "." + ExplainUtil.getExplainMapByList(jsonArray).get(condition.getSubAttr()).getAttrName());
                }
                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.STAGE_THRUSTER.getType())) {
                    //修正历史配置中阶段fieldType为3的老数据
                    resultCondition.setFieldType(FieldTypeEnum.STAGE_THRUSTER.getType());
                    transferStageCondition(resultCondition);
                }
                resultConditionList.add(resultCondition);
            }

        }
        return resultConditionList;
    }

    /**
     * 流程设定流转条件历史数据中客户线索机会阶段的code需要由数字转为字符串
     * @param condition
     */
    private void transferStageCondition(ConditionsEntityExt condition) {
        List<Object> stageValue = condition.getValue();
        if (CollectionsUtil.isNotEmpty(stageValue)) {
            for (int i = 0; i < stageValue.size(); i++) {
                stageValue.set(i, String.valueOf(stageValue.get(i)));
            }
            condition.setValue(stageValue);
        }
    }

    /**
     * 保存流程相关信息
     *
     * @param processUpdateDTO
     * @return ProcessUpdateVO
     * @throws XbbException 数据库异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProcessUpdateVO save(ProcessUpdateDTO processUpdateDTO) throws XbbException {
        ProcessUpdateVO processUpdateVO = new ProcessUpdateVO();
        String userId = processUpdateDTO.getUserId();
        Long formId = processUpdateDTO.getFormId();
        String corpId = processUpdateDTO.getCorpid();
        String userName = processUpdateDTO.getLoginUserName();
        processUpdateVO.setAppId(processUpdateDTO.getAppId());
        processUpdateVO.setFormId(formId);
        PaasProcessTemplateEntity processTemplateEntity = new PaasProcessTemplateEntity();

        try {
            // 更新流程
            ProcessTemplateUpdateDTO processTemplate = processUpdateDTO.getProcessTemplate();
            processUpdateVO.setTemplateId(processTemplate.getId());
            Map<String, Object> params = BeanUtil.convertBean2Map(processUpdateDTO, true);
            params.put("templateId", processTemplate.getId());
            Integer count = paasProcessTaskModel.getEntitysCount(params);
            boolean isHistory = count > 0;
            BeanUtils.copyProperties(processTemplate, processTemplateEntity);
            processTemplateEntity.setCorpid(corpId);
            // 转成String
            processTemplateEntity.setRolesWithoutApprove(JSONObject.toJSONString(processTemplate.getRolesWithoutApproveList()));
            processTemplateEntity.setNeedApproveFields(JSONObject.toJSONString(processTemplate.getNeedApproveFieldList()));
            processTemplateEntity.setSaasMark(processUpdateDTO.getSaasMark());
            processTemplateEntity.setBusinessType(processUpdateDTO.getBusinessType());
            processTemplateEntity.setUsePermission(processTemplate.getUsePermission());
            processTemplateModel.update(processTemplateEntity);

            List<NewProcessNodeDTO> newProcessNodeList = processUpdateDTO.getNewProcessNodeList();
            List<ProcessTemplateNodeUpdateDTO> nodeList = new ArrayList<>();
            for (NewProcessNodeDTO newProcessNodeDTO : newProcessNodeList) {
                JSONObject data = newProcessNodeDTO.getData();
                if (data == null) {
                    data = new JSONObject();
                }
                String json = JSONObject.toJSONString(data);
                ProcessTemplateNodeUpdateDTO processTemplateNodeUpdateDTO = JSONObject.parseObject(json, ProcessTemplateNodeUpdateDTO.class);
                // fix:33459 对各节点操作文案进行长度校验
                if ((processTemplateNodeUpdateDTO.getCommitText() != null && processTemplateNodeUpdateDTO.getCommitText().length() > 20)
                        || (processTemplateNodeUpdateDTO.getStorageText() != null && processTemplateNodeUpdateDTO.getStorageText().length() > 20)
                        || (processTemplateNodeUpdateDTO.getBackText() != null && processTemplateNodeUpdateDTO.getBackText().length() > 20)
                        || (processTemplateNodeUpdateDTO.getTransferText() != null && processTemplateNodeUpdateDTO.getTransferText().length() > 20)
                        || (processTemplateNodeUpdateDTO.getEndText() != null && processTemplateNodeUpdateDTO.getEndText().length() > 20)) {
                    throw new XbbException(ApprovalErrorCodeEnum.API_ERROR_209015.getCode(), ApprovalErrorCodeEnum.API_ERROR_209015.getMsg());
                }
                if (Objects.equals(newProcessNodeDTO.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType())
                        || Objects.equals(newProcessNodeDTO.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                    setDefaultValueForNode(processTemplateNodeUpdateDTO);
                }
                processTemplateNodeUpdateDTO.setName(newProcessNodeDTO.getName());
                processTemplateNodeUpdateDTO.setCondition(JSONArray.toJSONString(processTemplateNodeUpdateDTO.getConditions()));
                processTemplateNodeUpdateDTO.setPrevId(newProcessNodeDTO.getPrevId());
                processTemplateNodeUpdateDTO.setUid(newProcessNodeDTO.getNodeId());
                processTemplateNodeUpdateDTO.setType(newProcessNodeDTO.getType());
                processTemplateNodeUpdateDTO.setWrapperId(newProcessNodeDTO.getWrapperId());
                processTemplateNodeUpdateDTO.setPriority(newProcessNodeDTO.getPriority());
                processTemplateNodeUpdateDTO.setX(0D);
                processTemplateNodeUpdateDTO.setY(0D);
                nodeList.add(processTemplateNodeUpdateDTO);
            }
            processUpdateDTO.setNodeList(nodeList);
            updateProcessNode(processUpdateDTO, processTemplateEntity, isHistory);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库保存流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // 记录日志
        String formName = null;
        if (Objects.equals(processTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpId);
            if (workOrderEntity != null) {
                formName = workOrderEntity.getName();
            }
        } else {
            PaasFormEntityExt formEntity = paasFormModel.getByKey(formId, corpId);
            if (formEntity != null) {
                formName = formEntity.getName();
            }
        }
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_PROCESS_TEMPLATE), userName, formName);
        mongoLogHelp.buildLog(corpId, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                OperateTypeEnum.EDIT, formId.toString(), formName, memo, processUpdateDTO.getHttpHeader());

        return processUpdateVO;
    }

    /**
     * 流程启用/暂停
     *
     * @param processEnableDTO
     * @return ProcessEnableVO
     * @throws XbbException 数据库异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProcessEnableVO enable(ProcessEnableDTO processEnableDTO) throws XbbException {
        ProcessEnableVO processEnableVO = new ProcessEnableVO();
        try {
            if (Objects.equals(processEnableDTO.getEnable(), 1)) {
                Map<String, Object> params = BeanUtil.convertBean2Map(processEnableDTO, true);
                List<PaasProcessTemplateEntityExt> templateEntityList = processTemplateModel.list(params);
                if (!templateEntityList.isEmpty()) {
                    PaasProcessTemplateEntity processTemplateEntity = new PaasProcessTemplateEntity();
                    //22072 【成功部】多个流程版本启用切换，会导致审批人为空自动变成（转交给超管）
                    processTemplateEntity.setEmptyApproverType(null);
                    processTemplateEntity.setEnable(0);
                    processTemplateEntity.setCorpid(processEnableDTO.getCorpid());
                    processTemplateEntity.setId(templateEntityList.get(0).getId());
                    processTemplateModel.update(processTemplateEntity);
                } else {
                    PaasFormEntity paasFormEntity = new PaasFormEntity();
                    BeanUtil.copyProperties(processEnableDTO, paasFormEntity);
                    paasFormEntity.setId(processEnableDTO.getFormId());
                    // 将流程表单改为普通表单
                    updateFormType(paasFormEntity, 1, MenuTypeEnum.PROCESS_FORM.getType(), processEnableDTO.getUserId(), processEnableDTO.getLoginUserName(), processEnableDTO.getHttpHeader());
                }
            }

            PaasProcessTemplateEntity processTemplateEntity = new PaasProcessTemplateEntity();
            // 不更新审批人为空处理字段
            processTemplateEntity.setEmptyApproverType(null);
            processTemplateEntity.setApproverDeduplication(null);
            processTemplateEntity.setAutomaticallyApprovedSponsor(null);
            BeanUtils.copyProperties(processEnableDTO, processTemplateEntity);
            processTemplateEntity.setId(processEnableDTO.getProcessTemplateId());

            processTemplateModel.update(processTemplateEntity);
            BeanUtils.copyProperties(processEnableDTO, processEnableVO);

        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库启用/暂停流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // 记录日志
        String userId = processEnableDTO.getUserId();
        String corpId = processEnableDTO.getCorpid();
        String userName = processEnableDTO.getLoginUserName();
        String formName;
        if (Objects.equals(processEnableDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(processEnableDTO.getFormId(), corpId);
            if (workOrderFormEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            formName = workOrderFormEntityExt.getName();
        } else {
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(processEnableDTO.getFormId(), corpId);
            if (paasFormEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            formName = paasFormEntityExt.getName();
        }

        String memo;
        OperateTypeEnum operateTypeEnum;
        if (Objects.equals(BasicConstant.ONE, processEnableDTO.getEnable())) {
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_PROCESS_TEMPLATE_ENABLE), userName, formName);
            operateTypeEnum = OperateTypeEnum.ENABLE;
        } else {
            memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_PROCESS_TEMPLATE_CLOSE), userName, formName);
            operateTypeEnum = OperateTypeEnum.CLOSE;
        }
        mongoLogHelp.buildLog(corpId, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                operateTypeEnum, processEnableDTO.getFormId().toString(), formName, memo, processEnableDTO.getHttpHeader());

        return processEnableVO;
    }

    /**
     * 获取需审批字段列表
     *
     * @param needApproveDTO
     * @return NeedApproveVO
     * @throws XbbException 数据库异常
     */
    @Override
    public NeedApproveVO needApproveFields(NeedApproveDTO needApproveDTO) throws XbbException {
        NeedApproveVO needApproveVO = new NeedApproveVO();
        List<NeedApprovePojo> needApprovePojoList = new ArrayList<>();
        try {
            // 获取流程属性
            Map<String, FieldAttrEntity> explainMap = getExplainMap(needApproveDTO, needApproveDTO.getFormId(), needApproveDTO.getCorpid(), needApproveDTO.getBusinessType());
            List<Integer> showTypeList = Arrays.asList(ShowTypeEnum.ALL.getCode(), ShowTypeEnum.EDIT.getCode(), ShowTypeEnum.EDIT_LIST.getCode(), ShowTypeEnum.EDIT_DETAIL.getCode());
            Integer saasMark = needApproveDTO.getSaasMark();
            //确认是否为创建回款单
            SheetTypeEnum sheetTypeEnum = SheetTypeEnum.getByBusinessType(needApproveDTO.getBusinessType());
            boolean sheetFlag = SheetTypeEnum.validateSheet(sheetTypeEnum);
            List<String> unableEditAttrList = new ArrayList<>();
            if (sheetFlag) {
                //回/付款单编辑时禁止编辑的字段
                unableEditAttrList = fundHelp.getUnableEditAttrList(sheetTypeEnum, needApproveDTO.getDistributorMark());
            }
            for (Map.Entry<String, FieldAttrEntity> entry : explainMap.entrySet()) {
                FieldAttrEntity fieldAttrEntity = entry.getValue();
                if (Objects.equals(fieldAttrEntity.getIsOpen(), 0) || Objects.equals(fieldAttrEntity.getVisible(), 0) || Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                    continue;
                }
                Integer fieldType = fieldAttrEntity.getFieldType();
                if (Objects.equals(fieldType, FieldTypeEnum.SEPARATOR.getType()) || Objects.equals(fieldType, FieldTypeEnum.MEMO.getType()) || Objects.equals(fieldType, FieldTypeEnum.UPDATETIME.getType()) || Objects.equals(fieldType, FieldTypeEnum.TEMPLATE_FIELD.getType())) {
                    continue;
                }
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER_V2.getCode(), needApproveDTO.getBusinessType()) && Objects.equals(fieldAttrEntity.getAttr(), "text_4")) {
                    // 工单状态进审批
                }else if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode()) && Objects.equals(fieldAttrEntity.getIsRedundant(), 0) && !showTypeList.contains(fieldAttrEntity.getShowType())
                        || Objects.equals(fieldType, FieldTypeEnum.LINK_FORM.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.LINK_FORM_BUTTON.getType())) {
                    continue;
                }
                if (sheetFlag && unableEditAttrList.contains(fieldAttrEntity.getAttr())) {
                    //回/付款单/其他收入单/其他支出单本身就禁止编辑的字段，无需设置为需审批字段
                    continue;
                }

                //特殊无须审批字段 暂时兼容一下 这里的代码后面重构的时候再优化
                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.NOW_INTO_STAGE_TIME.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.FIRST_INTO_STAGE_TIME.getType())) {
                    continue;
                }
                //如果是工单业务的话，负责人字段不应该可以选择作为审批字段
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), needApproveDTO.getBusinessType()) &&
                    Objects.equals(FieldTypeEnum.OWNERID.getAlias(), fieldAttrEntity.getAttr())) {
                    continue;
                }

                if(Objects.equals(needApproveDTO.getBusinessType(),XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())
                        && Objects.equals(fieldAttrEntity.getAttr(), SalesOpportunityEnum.LINK_COMPETITOR.getAttr())){
                    continue;
                }

                needApprovePojoList.add(new NeedApprovePojo(entry.getKey(), fieldAttrEntity.getAttrName()));
            }
            needApproveVO.setList(needApprovePojoList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("获取需审批字段列表出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return needApproveVO;
    }

    @Override
    public ProcessFormFieldVO formFields(FormGetDTO formGetDTO) throws XbbException {
        ProcessFormFieldVO processFormFieldVO = new ProcessFormFieldVO();
        try {
            String corpid = formGetDTO.getCorpid();
            Integer businessType = formGetDTO.getBusinessType();
            // 查看表单主表信息
            PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(formGetDTO.getFormId(), corpid);
                if (Objects.isNull(workOrderFormEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                BeanUtil.copyProperties(workOrderFormEntity, paasFormEntityExt);
            } else {
                paasFormEntityExt = paasFormModel.getByKey(formGetDTO.getFormId(), corpid);
                if (Objects.isNull(paasFormEntityExt)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
            }
            FormEntityGetVO formEntityGetVO = new FormEntityGetVO();
            BeanUtils.copyProperties(paasFormEntityExt, formEntityGetVO);
            formEntityGetVO.setSummary(JSONArray.parseArray(paasFormEntityExt.getSummary(), SummaryDataPoJo.class));

            // 查看表单字段描述信息
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            if (Objects.equals(formGetDTO.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formGetDTO.getFormId(), corpid);
                if (Objects.isNull(workOrderExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                BeanUtil.copyProperties(workOrderExplainEntity, paasFormExplainEntity);
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(formGetDTO.getFormId(), corpid);
                if (Objects.isNull(paasFormExplainEntity)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            // 过滤某些不需要显示的字段
            List<ProcessFieldAttrPojo> processExplainList = new ArrayList<>();
            // 节点的字段解释需要和表单更新的解释一样需要format
            Integer saasMark = paasFormEntityExt.getSaasMark();
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
            List<Integer> showTypeList = commonHelp.processShowAttrFieldType();
            // 这个特殊操作简直了
            List<String> specialContractAttrList = Arrays.asList(ContractEnum.CONTRACT_COST.getAttr(), ContractEnum.GROSS_PROFIT.getAttr(), ContractEnum.GROSS_PROFIT_RATE.getAttr(),
                    ContractEnum.CASH_PROFIT.getAttr(), ContractEnum.CASH_PROFIT_RATE.getAttr());
            List<String> specialOpportunityAttrList = Arrays.asList(SalesOpportunityEnum.COST.getAttr(), SalesOpportunityEnum.GROSS_PROFIT.getAttr(), SalesOpportunityEnum.GROSS_PROFIT_RATE.getAttr());
            List<Integer> summaryList = Arrays.asList(1,2,3,4,9,10,12,10000,10001,10003,10009,10010,10011,10012,10013,10014,10015,10016,10017,10018,10019,10030,20001,20002);
            // 获取套餐功能
            List<String> featureList = packageHelp.getFeatureList(corpid);
            //审批优化需求关联产品字段放出来只需要支持工作流不支持老审批
            List<Integer> productHandleBusList = BusinessProductCompareEnum.getProductHandleBusList();
            boolean workflowCorpidTag = commonHelp.isOpenWorkFlow(corpid) && productHandleBusList.contains(businessType);
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                ProcessFieldAttrPojo processFieldAttrPojo = new ProcessFieldAttrPojo();
                BeanUtil.copyProperties(fieldAttrEntity, processFieldAttrPojo);
                if (Objects.equals(LocaleContextHolder.getLocale().getLanguage(), I18nStringConstant.ENGLISH_LANGUAGE)) {
                    processFieldAttrPojo.setAttrName(fieldAttrEntity.getAttrNameEn());
                    processFieldAttrPojo.setAttrNameEn(fieldAttrEntity.getAttrName());
                }
                Integer fieldType = fieldAttrEntity.getFieldType();
                Integer isRedundant = fieldAttrEntity.getIsRedundant();
                String attr = fieldAttrEntity.getAttr();
                if (Objects.equals(fieldType, FieldTypeEnum.ADDTIME.getType()) || Objects.equals(fieldType, FieldTypeEnum.UPDATETIME.getType())
                    || Objects.equals(fieldType, FieldTypeEnum.CREATORID.getType()) || Objects.equals(fieldType, FieldTypeEnum.MEMO.getType())
                        || Objects.equals(fieldType, FieldTypeEnum.PUBLIC_GROUP.getType())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                // 流水号开启严控模式
                if (Objects.equals(fieldAttrEntity.getAttr(), FieldTypeEnum.SERIALNO.getAlias()) && Objects.equals(fieldAttrEntity.getStrictController(), BasicConstant.ONE) ){
                    processFieldAttrPojo.setNoneEditable(1);
                }
                if (Objects.equals(attr, ClueEnum.CLUE_STATUS.getAttr()) && Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                //阶段比例不支持编辑
                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.STAGE_RATIO.getType())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                //客户退回次数
                if (Objects.equals(attr, ClueEnum.BACK_NUM.getAttr()) && Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                //线索退回次数
                if (Objects.equals(attr, CustomerManagementEnum.BACK_NUM.getAttr()) && Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                //机会 关联竞争对手
                if (Objects.equals(attr, SalesOpportunityEnum.LINK_COMPETITOR.getAttr()) && Objects.equals(businessType, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                //回执单金额
                if ((Objects.equals(attr, ReceiptOrderEnum.PRODUCT_TOTAL.getAttr()) || Objects.equals(attr, ReceiptOrderEnum.SERVICE_TOTAL.getAttr())
                        || Objects.equals(attr, ReceiptOrderEnum.LINK_WORK_ORDER.getAttr()) || Objects.equals(attr, ReceiptOrderEnum.LINK_CUSTOMER.getAttr()))
                        && Objects.equals(businessType, XbbRefTypeEnum.RECEIPT_ORDER.getCode())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                // 字段是否开启
                if (Objects.equals(fieldAttrEntity.getIsOpen(), 0) || Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                    continue;
                }
                if (Objects.equals(businessType, XbbRefTypeEnum.SUPPLIER.getCode()) && Objects.equals(fieldAttrEntity.getAttr(), SupplierEnum.PRODUCT_LIST.getAttr())) {
                    continue;
                }
                if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType()) || Objects.equals(fieldType, FieldTypeEnum.CONTACT_NUMBER.getType())) {
                    processFieldAttrPojo.setSummary(0);
                    List<? extends FieldAttrEntity> jsonArray = processFieldAttrPojo.getSubForm().getItems();
                    Iterator<? extends FieldAttrEntity> iterator = jsonArray.iterator();
                    while (iterator.hasNext()) {
                        FieldAttrEntity item = iterator.next();
                        // 字段删除处理
                        if (Objects.equals(item.getIsOpen(), 2)) {
                            iterator.remove();
                            continue;
                        }
                        item.setSummary(0);
                        // 套餐逻辑，标准版本隐藏复杂字段
                        packageHelp.explainDesignHide(featureList, item);
                        if (Objects.equals(item.getEditHide(), 1)) {
                            iterator.remove();
                        }
                    }
                } else if (ExplainUtil.isSubForm(fieldType)) {
                    List<FieldAttrEntity> newJsonArray = new ArrayList<>();
                    List<? extends FieldAttrEntity> jsonArray = processFieldAttrPojo.getSubForm().getItems();
                    Iterator<? extends FieldAttrEntity> iterator = jsonArray.iterator();
                    while (iterator.hasNext()) {
                        FieldAttrEntity item = iterator.next();
                        // 字段删除处理
                        if (Objects.equals(item.getIsOpen(), 2)) {
                            iterator.remove();
                            continue;
                        }
                        // 套餐逻辑，标准版本隐藏复杂字段
                        packageHelp.explainDesignHide(featureList, item);
                        if (Objects.equals(item.getEditHide(), 1)) {
                            iterator.remove();
                            continue;
                        }
                        //下面对关联产品里面的字段有些特殊操作
                        if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), fieldType) && workflowCorpidTag) {
                            if (Objects.equals(BasicConstant.ZERO, item.getIsRedundant())) {
                                if (!showTypeList.contains(item.getShowType())) {
                                    iterator.remove();
                                    continue;
                                }
                            }
                            if (!Objects.equals(BasicConstant.ONE, item.getIsOpen())) {
                                iterator.remove();
                                continue;
                            }
                            ProcessFieldAttrPojo processFieldAttrPojoSen = new ProcessFieldAttrPojo();
                            BeanUtil.copyProperties(item, processFieldAttrPojoSen);
                            List<String> unEditableFieldList = BusinessProductCompareEnum.getAllUnEditableFieldList(businessType);
                            if (unEditableFieldList.contains(item.getAttr())) {
                                processFieldAttrPojoSen.setEditable(BasicConstant.ZERO);
                                processFieldAttrPojoSen.setNoneEditable(BasicConstant.ONE);
                            }
                            newJsonArray.add(processFieldAttrPojoSen);
                        }
                    }
                    if (workflowCorpidTag) {
                        processFieldAttrPojo.getSubForm().setItems(newJsonArray);
                    }
                }
                if (summaryList.contains(fieldType)) {
                    // 1：可以显示展示摘要；
                    processFieldAttrPojo.setSummary(1);
                } else {
                    // 0：不能展示摘要；
                    processFieldAttrPojo.setSummary(0);
                }
                // 套餐逻辑，标准版本隐藏复杂字段
                Integer hide = packageHelp.processHide(featureList, processFieldAttrPojo);
                if (Objects.equals(0, hide)) {
                    continue;
                }

                if (Objects.equals(isRedundant, 0)) {
                    // 是否在设计阶段展示，或showType 0:全部显示 1:新建编辑显示 4:新建编辑，列表显示 5:新建编辑，详情显示
                    if (commonHelp.processNotShow(fieldAttrEntity.getEditHide(), fieldAttrEntity.getShowType(), showTypeList)) {
                        continue;
                    } else {
                        processFieldAttrPojo.setCanShow(1);
                    }
                    // 模板禁用了修改必填选项，所以审批也必填禁用
                    if (Objects.equals(fieldAttrEntity.getIsForbidden(), 0)) {
                        processFieldAttrPojo.setMustShow(1);
                    }
                    setSaasSpecialField(attr, fieldType, xbbRefTypeEnum, processFieldAttrPojo, specialContractAttrList, specialOpportunityAttrList, paasFormExplainEntity, workflowCorpidTag);
                } else {
                    if (commonHelp.paasProcessNotShow(fieldAttrEntity.getEditHide(), fieldAttrEntity.getShowType(), showTypeList)) {
                        continue;
                    }
                    processFieldAttrPojo.setCanShow(1);
                }
                processExplainList.add(processFieldAttrPojo);
            }
            formEntityGetVO.setSaasMark(saasMark);
            formEntityGetVO.setBusinessType(paasFormEntityExt.getBusinessType());
            processFormFieldVO.setAppId(formGetDTO.getAppId());
            processFormFieldVO.setFormAttr(formEntityGetVO);
            processFormFieldVO.setFormId(paasFormEntityExt.getId());
            processFormFieldVO.setMenuId(paasFormEntityExt.getMenuId());
            processFormFieldVO.setExplainList(processExplainList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasForm数据库查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processFormFieldVO;
    }

    @Override
    public ProcessParamsVO processParams(ProcessParamsDTO processParamsDTO) throws XbbException {
        ProcessParamsVO processParamsVO = new ProcessParamsVO();
        BeanUtil.copyProperties(processParamsDTO, processParamsVO);
        return processParamsVO;
    }

    @Override
    public void initProcessNode(ProcessDTO processDTO) throws XbbException {
        List<String> corpidList = processDTO.getCorpidList();
        String attr = processDTO.getAttr();
        Integer visible = processDTO.getVisible();
        Integer editable = processDTO.getEditable();
        for (String corpid : corpidList) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("businessType", processDTO.getBusinessType());
            params.put("del", 0);
            params.put("corpid", corpid);
            List<PaasProcessTemplateEntityExt> templateEntities = paasProcessTemplateModel.list(params);
            if (!templateEntities.isEmpty()) {
                for (PaasProcessTemplateEntityExt templateEntity : templateEntities) {
                    params.put("templateId", templateEntity.getId());
                    List<PaasProcessTemplateNodeEntityExt> nodeEntityList = paasProcessTemplateNodeModel.list(params);
                    List<PaasProcessTemplateNodeEntityExt> nodeEntities = new ArrayList<>();
                    for (PaasProcessTemplateNodeEntityExt nodeEntityExt : nodeEntityList) {
                        PaasProcessTemplateNodeEntityExt paasProcessTemplateNodeEntity = new PaasProcessTemplateNodeEntityExt();
                        paasProcessTemplateNodeEntity.setId(nodeEntityExt.getId());
                        List<FieldPermissionEntityExt> fieldPermissions = nodeEntityExt.getFieldPermissionList();
                        if (fieldPermissions != null) {
                            for (FieldPermissionEntityExt fieldPermission : fieldPermissions) {
                                if (Objects.equals(attr, fieldPermission.getAttr())) {
                                    if(Objects.nonNull(visible)) {
                                        fieldPermission.setVisible(visible);
                                    }
                                    if(Objects.nonNull(editable)) {
                                        fieldPermission.setEditable(editable);
                                    }
                                    break;
                                }
                            }
                        }
                        paasProcessTemplateNodeEntity.setFieldPermission(JSON.toJSONString(fieldPermissions));
                        nodeEntities.add(paasProcessTemplateNodeEntity);
                    }
                    paasProcessTemplateNodeModel.updateBatch(nodeEntities, corpid);
                }
            }
        }
    }

    @Override
    public ProcessVersionVO processVersion(ProcessVersionDTO processVersionDTO) throws XbbException {
        ProcessVersionVO processVersionVO = new ProcessVersionVO();
        BeanUtil.copyProperties(processVersionDTO, processVersionDTO);
        try {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, processVersionDTO.getCorpid());
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put(StringConstant.FORM_ID, processVersionDTO.getFormId());
            params.put(StringConstant.SAAS_MARK, processVersionDTO.getSaasMark());
            params.put(StringConstant.BUSINESS_TYPE, processVersionDTO.getBusinessType());
            params.put("orderByStr", " version_id " + SortOrder.ASC);
            params.put("isArchive", processVersionDTO.getArchive());
            Integer entitysCount = 0;
            Integer pageSize = processVersionDTO.getPageSize();
            Integer page = processVersionDTO.getPage();
            if (Objects.equals(processVersionDTO.getArchive(), BasicConstant.ONE)) {
                entitysCount = processTemplateModel.getEntitysCount(params);
                params.put("start", (page - 1) * pageSize);
                params.put("pageNum", pageSize);
            }
            List<PaasProcessTemplateEntityExt> tempList = processTemplateModel.list(params);
            Set<Long> haveTaskSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (Objects.equals(processVersionDTO.getArchive(), BasicConstant.TWO)) {
                params.remove("orderByStr");
                params.put(StringConstant.COLUMNS, " DISTINCT(template_id) ");
                List<PaasProcessTaskEntity> taskEntityList = paasProcessTaskModel.findEntitys(params);
                taskEntityList.forEach(item -> {
                    if (!haveTaskSet.contains(item.getTemplateId())) {
                        haveTaskSet.add(item.getTemplateId());
                    }
                });
            }
            List<ProcessVersionPojo> processVersionPojoList = new ArrayList<>();
            for (PaasProcessTemplateEntityExt paasProcessTemplateEntityExt : tempList) {
                ProcessVersionPojo processVersionPojo = new ProcessVersionPojo();
                processVersionPojo.setProcessTemplateId(paasProcessTemplateEntityExt.getId());
                processVersionPojo.setVersionName(paasProcessTemplateEntityExt.getVersionName());
                processVersionPojo.setVersionId(paasProcessTemplateEntityExt.getVersionId());
                if (Objects.equals(processVersionDTO.getArchive(), BasicConstant.TWO)) {
                    if (StringUtil.isEmpty(paasProcessTemplateEntityExt.getVersionName())) {
                        processVersionPojo.setVersionName("v1");
                    }
                    if (paasProcessTemplateEntityExt.getVersionId() == null) {
                        processVersionPojo.setVersionId(1);
                    }
                    if (Objects.equals(paasProcessTemplateEntityExt.getEnable(), 1)) {
                        processVersionPojo.setVersionType(2);
                        processVersionPojoList.add(0, processVersionPojo);
                    } else {
                        if (haveTaskSet.contains(paasProcessTemplateEntityExt.getId())) {
                            processVersionPojo.setVersionType(3);
                        }else {
                            processVersionPojo.setVersionType(1);
                        }
                        processVersionPojoList.add(processVersionPojo);
                    }
                }else {
                    processVersionPojoList.add(processVersionPojo);
                }
            }
            PageHelper pageHelper = new PageHelper(page, pageSize);
            pageHelper.setRowsCount(entitysCount);
            processVersionVO.setPageHelper(pageHelper);
            processVersionVO.setProcessVersionPojoList(processVersionPojoList);
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate获取流程版本出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processVersionVO;
    }

    @Override
    public ProcessGetVO add(ProcessGetDTO processGetDTO) throws XbbException {
        ProcessGetVO processGetVO = new ProcessGetVO();
        try {
            Map<String, Object> params = BeanUtil.convertBean2Map(processGetDTO, true);
            params.put("orderByStr", " version_id DESC ");
            List<PaasProcessTemplateEntityExt> processList = processTemplateModel.list(params);
            int versionId = 1;
            PaasProcessTemplateEntityExt newTempEntity = null;
            Integer count = 1;
            for (PaasProcessTemplateEntityExt item : processList) {
                if (Objects.equals(item.getIsArchive(), BasicConstant.TWO)) {
                    count++;
                }
            }
            if (count > 50){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_MAX_LIMIT);
            }
            if (processList.size() > 550) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_SIZE_MAX_LIMIT);
            }
            for (int i = 0; i < processList.size() ; i++) {
                PaasProcessTemplateEntityExt paasProcessTemplateEntityExt = processList.get(i);
                if (i == 0) {
                    versionId = paasProcessTemplateEntityExt.getVersionId() + 1;
                }
                if (Objects.equals(processGetDTO.getProcessTemplateId(), paasProcessTemplateEntityExt.getId())) {
                    newTempEntity = paasProcessTemplateEntityExt;
                    newTempEntity.setCreatorId(processGetDTO.getUserId());
                    break;
                }
            }
            if (Objects.isNull(newTempEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NOT_EXIST);
            }
            params.clear();
            params.put("corpid", processGetDTO.getCorpid());
            params.put("del", 0);
            params.put("templateId", processGetDTO.getProcessTemplateId());
            List<PaasProcessTemplateNodeEntityExt> templateNodeEntityList = paasProcessTemplateNodeModel.list(params);
            if (templateNodeEntityList.size() == 0) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NOT_EXIST);
            }
            newTempEntity.setId(null);
            newTempEntity.setVersionId(versionId);
            newTempEntity.setVersionName("v" + versionId);
            newTempEntity.setEnable(0);
            processTemplateModel.insert(newTempEntity);
            processGetVO.setProcessTemplate(newTempEntity);
            for (PaasProcessTemplateNodeEntityExt paasProcessTemplateNodeEntityExt : templateNodeEntityList) {
                paasProcessTemplateNodeEntityExt.setId(null);
                paasProcessTemplateNodeEntityExt.setTemplateId(newTempEntity.getId());
            }
            paasProcessTemplateNodeModel.insertBatch(templateNodeEntityList);
            getProcessTree(processGetDTO, processGetVO, newTempEntity, templateNodeEntityList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库新增模板出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return processGetVO;
    }

    /**
     * 更新流程节点
     *
     * @param processUpdateDTO      前端所传对象
     * @param processTemplateEntity 流程模板
     * @throws XbbException
     */
    private void updateProcessNode(ProcessUpdateDTO processUpdateDTO, PaasProcessTemplateEntity processTemplateEntity, boolean isHistory) throws XbbException {
        List<PaasProcessTemplateNodeEntityExt> nodeEntityAddList = new ArrayList<>();
        List<PaasProcessTemplateNodeEntityExt> nodeEntityUpdateList = new ArrayList<>();
        try {
            Map<String, Object> params = BeanUtil.convertBean2Map(processUpdateDTO, true);
            params.remove("type");
            params.put("templateId", processTemplateEntity.getId());
            List<PaasProcessTemplateNodeEntityExt> nodeList = paasProcessTemplateNodeModel.list(params);

            Map<String, PaasProcessTemplateNodeEntityExt> nodeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 将已有的节点数据转成集合
            nodeList.forEach(item -> nodeMap.put(item.getUid(), item));
            // 遍历找出哪些是更新节点，哪些是新增节点，
            for (ProcessTemplateNodeUpdateDTO node : processUpdateDTO.getNodeList()) {
                PaasProcessTemplateNodeEntityExt entity = new PaasProcessTemplateNodeEntityExt();
                BeanUtils.copyProperties(node, entity);
                entity.setCorpid(processUpdateDTO.getCorpid());
                if (Objects.equals(node.getType(), NodeTypeEnum.PROCESS_NODE.getNodeType()) && node.getMainUserList().isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MAIN_USER_NOT_SET, node.getName());
                }
                if (Objects.equals(node.getType(), NodeTypeEnum.CC_PROCESS_NODE.getNodeType()) && node.getCcUserList().isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.CC_USER_NOT_SET, node.getName());
                }
                if (Objects.equals(node.getTransferFlag(), 1) && node.getTransferUserList().isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.TRANSFER_USER_NOT_SET, node.getName());
                }
                if (Objects.equals(node.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType())
                        || Objects.equals(node.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                    List<Object> list = new ArrayList<>();
                    entity.setMainUser(JSONArray.toJSONString(list));
                    entity.setCcUser(JSONArray.toJSONString(list));
                    entity.setTransferUser(JSONArray.toJSONString(list));
                    entity.setBackNode(JSONArray.toJSONString(list));
                    entity.setCommitVerifyCondition(JSONArray.toJSONString(list));
                    entity.setFieldPermission(JSONArray.toJSONString(list));
                } else {
                    entity.setMainUser(JSONArray.toJSONString(node.getMainUserList()));
                    entity.setCcUser(JSONArray.toJSONString(node.getCcUserList()));
                    entity.setTransferUser(JSONArray.toJSONString(node.getTransferUserList()));
                    entity.setBackNode(JSONArray.toJSONString(node.getBackNodeList()));
                    entity.setCommitVerifyCondition(JSONArray.toJSONString(new ArrayList<>()));
                    entity.setCondition("");
                    List<FieldPermissionEntityExt> permissionEntityExtList = new ArrayList<>();
                    node.getFieldPermissionMap().forEach((key,item) -> permissionEntityExtList.add(item));
                    entity.setFieldPermission(JSONArray.toJSONString(permissionEntityExtList));
                }

                long now = DateUtil.getInt();
                entity.setUpdateTime(now);
                // 如果数据库中的节点的uid不包含前端提交来的uid，则为新建节点
                if (nodeMap.containsKey(node.getUid())) {
                    nodeEntityUpdateList.add(entity);
                } else {
                    entity.setFormId(processUpdateDTO.getFormId());
                    entity.setAppId(processUpdateDTO.getAppId());
                    entity.setTemplateId(processTemplateEntity.getId());
                    entity.setCreatorId(processUpdateDTO.getUserId());
                    entity.setMenuId(processUpdateDTO.getMenuId());
                    entity.setAddTime(now);
                    entity.setEnable(1);
                    entity.setTimeoutHandle("");
                    entity.setPrintTemplateId(0L);
                    nodeEntityAddList.add(entity);
                }
            }
            // 获取删除的节点
            List<PaasProcessTemplateNodeEntityExt> nodeEntityDeleteList = getNodeDeleteList(nodeList, processUpdateDTO.getNodeList());
            if (!nodeEntityDeleteList.isEmpty() && isHistory) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.NOT_ALLOWED_DEL_NODE);
            }
            // 节点操作
            processTemplateNodeService.nodeOperate(nodeEntityAddList, nodeEntityUpdateList, nodeEntityDeleteList, processTemplateEntity, processUpdateDTO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库更新流程节点出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private void removeSaasHiddenField(List<PaasProcessTemplateNodeEntityExt> processNodeList, List<FieldAttrEntity> explainList) {
        JSONArray jsonArray = new JSONArray();
        List<Integer> showTypeList = Arrays.asList(ShowTypeEnum.ALL.getCode(), ShowTypeEnum.EDIT.getCode(), ShowTypeEnum.EDIT_LIST.getCode(), ShowTypeEnum.EDIT_DETAIL.getCode());
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if ((Objects.equals(fieldAttrEntity.getIsRedundant(), 0) && (!showTypeList.contains(fieldAttrEntity.getShowType()) || Objects.equals(fieldAttrEntity.getEditHide(), 1)))
                    || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.CREATORID.getType()) || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.ADDTIME.getType())) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("attr", fieldAttrEntity.getAttr());
                jsonArray.add(jsonObject);
            }
        }
        removeHiddenField(processNodeList, jsonArray);
    }

    private void removeHiddenField(List<PaasProcessTemplateNodeEntityExt> processNodeList, JSONArray jsonArray) {
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            map.put(jsonObject.getString("attr"), jsonObject);
        }
        for (PaasProcessTemplateNodeEntityExt paasProcessTemplateNodeEntityExt : processNodeList) {
            List<FieldPermissionEntityExt> permissionEntityExtList = paasProcessTemplateNodeEntityExt.getFieldPermissionList();
            permissionEntityExtList.removeIf(fieldPermissionEntityExt -> map.containsKey(fieldPermissionEntityExt.getAttr()));
        }
    }

    /**
     * 获取删除的节点
     *
     * @param nodeList       已有节点列表
     * @param nodeUpdateList 更新的列表
     * @throws XbbException
     */
    private List<PaasProcessTemplateNodeEntityExt> getNodeDeleteList(List<PaasProcessTemplateNodeEntityExt> nodeList, List<ProcessTemplateNodeUpdateDTO> nodeUpdateList) throws XbbException {
        List<PaasProcessTemplateNodeEntityExt> nodeEntityDeleteList = new ArrayList<>();
        try {
            Map<Long, ProcessTemplateNodeUpdateDTO> nodeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ProcessTemplateNodeUpdateDTO nodeUpdate : nodeUpdateList) {
                if (nodeUpdate != null) {
                    nodeMap.put(nodeUpdate.getId(), nodeUpdate);
                }
            }
            for (PaasProcessTemplateNodeEntityExt node : nodeList) {
                if (!nodeMap.containsKey(node.getId())) {
                    PaasProcessTemplateNodeEntityExt paasProcessTemplateNodeEntity = new PaasProcessTemplateNodeEntityExt();
                    paasProcessTemplateNodeEntity.setId(node.getId());
                    paasProcessTemplateNodeEntity.setCorpid(node.getCorpid());
                    nodeEntityDeleteList.add(paasProcessTemplateNodeEntity);
                }
            }
        } catch (Exception e) {
            LOG.error("获取需要删除的节点出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return nodeEntityDeleteList;
    }

    /**
     * 新建流程，并初始化开始节点和结束节点
     *
     * @param processOpenDTO
     * @return
     * @throws XbbException
     */
    private ProcessOpenVO createProcess(ProcessOpenDTO processOpenDTO) throws XbbException {
        ProcessOpenVO processOpenVO = new ProcessOpenVO();
        String corpId = processOpenDTO.getCorpid();
        String userId = processOpenDTO.getUserId();
        Long formId = processOpenDTO.getFormId();
        String userName = processOpenDTO.getLoginUserName();
        PaasProcessTemplateEntity paasProcessTemplateEntity = new PaasProcessTemplateEntity();
        try {
            // 将表单主表更新为流程表单
            PaasFormEntity paasFormEntity = new PaasFormEntity();
            BeanUtil.copyProperties(processOpenDTO, paasFormEntity, true);
            paasFormEntity.setId(formId);
            updateFormType(paasFormEntity, 1, MenuTypeEnum.PROCESS_FORM.getType(), userId, userName, processOpenDTO.getHttpHeader());
            // 初始化流程
            ProcessTemplateAddDTO processTemplateAddDTO = new ProcessTemplateAddDTO();
            BeanUtil.copyProperties(processOpenDTO, processTemplateAddDTO, true);
            BeanUtils.copyProperties(processTemplateAddDTO, paasProcessTemplateEntity);
            paasProcessTemplateEntity.setCreatorId(userId);
            paasProcessTemplateEntity.setRolesWithoutApprove(JSONArray.toJSONString(processTemplateAddDTO.getRolesWithoutApprove()));
            paasProcessTemplateEntity.setNeedApproveFields(JSONArray.toJSONString(processTemplateAddDTO.getNeedApproveFields()));
            paasProcessTemplateEntity.setVersionName("v1");
            paasProcessTemplateEntity.setVersionId(1);
            paasProcessTemplateEntity.setUsePermission(1);
            paasProcessTemplateEntity.setIsArchive(2);
            // 默认为超管转交处理
            paasProcessTemplateEntity.setEmptyApproverType(1);
            // 默认不去重
            paasProcessTemplateEntity.setApproverDeduplication(3);
            // 默认发起人审批是不自动通过
            paasProcessTemplateEntity.setAutomaticallyApprovedSponsor(0);
            Integer templateId = processTemplateModel.insert(paasProcessTemplateEntity);

            // 初始化流程节点--增加开始节点，结束节点
            processTemplateNodeService.insertInitProcessTemplateNode(processOpenDTO, paasProcessTemplateEntity);

            BeanUtils.copyProperties(processOpenDTO, processOpenVO);
            processOpenVO.setProcessTemplateId(templateId.longValue());
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库开启流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // 记录日志
        String formName = null;
        if (Objects.equals(paasProcessTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpId);
            if (workOrderEntity != null) {
                formName = workOrderEntity.getName();
            }
        } else {
            PaasFormEntityExt formEntity = paasFormModel.getByKey(formId, corpId);
            if (formEntity != null) {
                formName = formEntity.getName();
            }
        }
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_PROCESS_TEMPLATE), userName, formName);
        mongoLogHelp.buildLog(corpId, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                OperateTypeEnum.NEW, formId.toString(), formName, memo, processOpenDTO.getHttpHeader());

        return processOpenVO;
    }

    @Override
    public ProcessOpenVO createProcess4Distributor(ProcessOpenDistributorDTO processOpenDistributorDTO) throws XbbException {
        String corpid = processOpenDistributorDTO.getCorpid();
        Long appId = processOpenDistributorDTO.getAppId();
        Long menuId = processOpenDistributorDTO.getMenuId();
        Long formId = processOpenDistributorDTO.getFormId();
        Integer businessType = processOpenDistributorDTO.getBusinessType();
        ProcessOpenVO processOpenVO = new ProcessOpenVO();
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put(StringConstant.CORPID, corpid);
        map.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        map.put(StringConstant.SAAS_MARK, processOpenDistributorDTO.getSaasMark());
        map.put("formId", formId);
        map.put("businessType", businessType);
        map.put("type", processOpenDistributorDTO.getType());
        List<PaasProcessTemplateEntityExt> templateList = processTemplateModel.list(map);
        if (CollectionUtils.isEmpty(templateList)) {
            //只有第一次为空时才初始化
            PaasProcessTemplateEntity paasProcessTemplateEntity = new PaasProcessTemplateEntity();
            try {
                String userId = processOpenDistributorDTO.getUserId();
                // 初始化流程
                ProcessTemplateAddDTO processTemplateAddDTO = new ProcessTemplateAddDTO();
                BeanUtil.copyProperties(processOpenDistributorDTO, processTemplateAddDTO, true);
                BeanUtils.copyProperties(processTemplateAddDTO, paasProcessTemplateEntity);
                paasProcessTemplateEntity.setCreatorId(userId);
                paasProcessTemplateEntity.setRolesWithoutApprove(JSONArray.toJSONString(processTemplateAddDTO.getRolesWithoutApprove()));
                paasProcessTemplateEntity.setNeedApproveFields(JSONArray.toJSONString(processTemplateAddDTO.getNeedApproveFields()));
                paasProcessTemplateEntity.setVersionName("v1");
                paasProcessTemplateEntity.setVersionId(1);
                paasProcessTemplateEntity.setUsePermission(1);
                //初始化的审批流程，默认开启
                paasProcessTemplateEntity.setEnable(EnableEnum.OPEN.getCode());
                paasProcessTemplateEntity.setIsArchive(2);
                // 默认为超管转交处理
                paasProcessTemplateEntity.setEmptyApproverType(1);
                // 默认不去重
                paasProcessTemplateEntity.setApproverDeduplication(3);
                // 默认发起人审批是不自动通过
                paasProcessTemplateEntity.setAutomaticallyApprovedSponsor(0);
                processTemplateModel.insert(paasProcessTemplateEntity);

                List<Integer> showTypeList = commonHelp.processShowAttrFieldType();
                List<DefaultDistributorProcessEnum> distributorProcessEnumList = DefaultDistributorProcessEnum.getByBusinessType(businessType);
//                TODO 渠道主管角色处理
                /*
                 key：业务类型
                 value：数组格式
                 */
                Map<Integer, List<FieldPermissionEntityExt>> businessFieldPermissionMap = fundHelp.getDefaultFieldPermission4Distributor(businessType, showTypeList);
                /*
                 key：优先级，DefaultDistributorProcessEnum 内的uuid
                 value：条件，数组格式
                 */
                Map<String, List<ConditionsEntityExt>> conditionMap = fundHelp.getDefaultConditions4Distributor(businessType);

                if (CollectionUtils.isNotEmpty(distributorProcessEnumList)) {
                    List<PaasProcessTemplateNodeEntityExt> nodeEntityUpdateList = new ArrayList<>();
                    for (DefaultDistributorProcessEnum anEnum : distributorProcessEnumList) {
                        PaasProcessTemplateNodeEntityExt entityExt = new PaasProcessTemplateNodeEntityExt(true, corpid, appId, menuId, formId, paasProcessTemplateEntity.getId());
                        BeanUtil.copyProperties(anEnum, entityExt, true);
                        List<FieldPermissionEntityExt> list = businessFieldPermissionMap.get(anEnum.getBusinessType());
                        if (Objects.nonNull(list)) {
                            entityExt.setFieldPermission(JSON.toJSONString(list));
                        } else {
                            entityExt.setFieldPermission(JSON.toJSONString(new JSONArray()));
                        }
                        if (Objects.equals(anEnum.getType(), NodeTypeEnum.CONDITION_PROCESS_NODE.getNodeType())) {
                            //只有条件节点才设置条件
                            List<ConditionsEntityExt> conditionsList = conditionMap.get(anEnum.getUid());
                            if (Objects.nonNull(conditionsList)) {
                                entityExt.setCondition(JSON.toJSONString(conditionsList));
                            } else {
                                entityExt.setCondition("[]");
                            }
                        }
                        entityExt.setCreatorId("1");
                        nodeEntityUpdateList.add(entityExt);
                    }
                    if (nodeEntityUpdateList.size() > 0) {
                        //保存流程节点
                        paasProcessTemplateNodeModel.insertBatch(nodeEntityUpdateList);
                    }
                } else {
                    // 如果枚举读取不到，则只初始化开始节点，结束节点
                    processTemplateNodeService.insertInitProcessTemplateNode(processOpenDistributorDTO, paasProcessTemplateEntity);
                }
            } catch (Exception e) {
                LOG.error("PaasProcessTemplate.createProcess4Distributor 开启经销商时数据库开启流程出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
        }
        return processOpenVO;
    }

    /**
     * 更新表单类型
     *
     * @param paasFormEntity
     * @param isProcessForm  是否流程表单，1是，0否
     * @param formType       菜单类型，1 分组，2 表单，3 表单(开启流程)，4 统计
     * @return
     * @throws XbbException
     */
    private void updateFormType(PaasFormEntity paasFormEntity, Integer isProcessForm, Integer formType, String userId, String userName, String header) throws XbbException {
        String formName;
        try {
            Long menuId = paasFormEntity.getMenuId();
            String corpid = paasFormEntity.getCorpid();
            Map<String, Object> params = BeanUtil.convertBean2Map(paasFormEntity, true);
            params.remove("enable");
            OperateModuleTypeEnum operateModuleType;
            if (Objects.equals(paasFormEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                List<WorkOrderFormEntity> workOrderList = workOrderFormModel.findEntitys(params);
                if (workOrderList == null || workOrderList.isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                WorkOrderFormEntity formEntity = new WorkOrderFormEntity();
                formEntity.setId(paasFormEntity.getId());
                formEntity.setCorpid(corpid);
                formEntity.setIsProcessForm(isProcessForm);
                workOrderFormModel.update(formEntity);
                operateModuleType = OperateModuleTypeEnum.PAAS_FORM_WORK_ORDER;
                formName = workOrderList.get(0).getName();
            } else {
                List<PaasFormEntityExt> list = paasFormModel.list(params);
                if (list == null || list.isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
                }
                PaasFormEntity formEntity = new PaasFormEntity();
                formEntity.setId(paasFormEntity.getId());
                formEntity.setCorpid(corpid);
                formEntity.setIsProcessForm(isProcessForm);
                paasFormModel.update(formEntity);
                operateModuleType = OperateModuleTypeEnum.PAAS_FORM;
                formName = list.get(0).getName();
            }

            // 记录日志
            String isProcessFormStr = Objects.equals(isProcessForm, 1) ? MenuTypeEnum.PROCESS_FORM.getMemo() : MenuTypeEnum.FORM.getMemo();
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_TYPE), userName, formName, isProcessFormStr);
            mongoLogHelp.buildLog(corpid, userId, userName, operateModuleType, OperateTypeEnum.EDIT, paasFormEntity.getId().toString(), formName, memo, header);

            // 将菜单的菜单类型改为流程表单类型
            if (!Objects.equals(paasFormEntity.getBusinessType(), XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())
                && !Objects.equals(paasFormEntity.getBusinessType(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())
                && !Objects.equals(paasFormEntity.getBusinessType(), XbbRefTypeEnum.CLUE.getCode())) {
                PaasMenuEntity paasMenuEntity = new PaasMenuEntity();
                paasMenuEntity.setId(menuId);
                paasMenuEntity.setType(formType);
                paasMenuEntity.setCorpid(corpid);
                paasMenuModel.update(paasMenuEntity);
                paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
                String name = paasMenuEntity == null ? XbbRefTypeEnum.getByCode(paasFormEntity.getBusinessType()).getName() : paasMenuEntity.getName();
                // 记录日志
                memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_MENU_TYPE), userName, name, isProcessFormStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_MENU, OperateTypeEnum.EDIT, menuId.toString(), name, memo, header);
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate更新表单和菜单类型出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private ProcessTreeVO buildTree(List<ProcessTreeVO> treeNodes) {
        ProcessTreeVO tree = new ProcessTreeVO();
        for (ProcessTreeVO treeNode : treeNodes) {
            if (Objects.equals(treeNode.getPrevId(), BasicConstant.ZERO.toString())) {
                tree = findChildren(treeNode,treeNodes);
                break;
            }
        }
        return tree;
    }

    private ProcessTreeVO findChildren(ProcessTreeVO treeNode,List<ProcessTreeVO> treeNodes) {
        for (ProcessTreeVO it : treeNodes) {
            if(treeNode.getNodeId().equals(it.getPrevId())) {
                if (Objects.equals(treeNode.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                    if (treeNode.getConditionNodes() == null) {
                        treeNode.setConditionNodes(new ArrayList<>());
                    }
                    ProcessTreeVO childrenNode = findChildren(it,treeNodes);
                    if (Objects.equals(childrenNode.getType(), NodeTypeEnum.PROCESS_NODE.getNodeType())
                        || Objects.equals(childrenNode.getType(), NodeTypeEnum.CC_PROCESS_NODE.getNodeType())
                        || Objects.equals(childrenNode.getType(), NodeTypeEnum.CONDITION_WRAPPER_PROCESS_NODE.getNodeType())) {
                        treeNode.setChildNode(childrenNode);
                    } else {
                        if (!treeNode.getConditionNodes().contains(childrenNode)) {
                            treeNode.getConditionNodes().add(childrenNode);
                        }
                    }
                } else {
                    treeNode.setChildNode(findChildren(it,treeNodes));
                }
            }
        }
        return treeNode;
    }

    private void setDefaultValueForNode(ProcessTemplateNodeUpdateDTO processTemplateNodeUpdateDTO) {
        processTemplateNodeUpdateDTO.setEnableCCFlag(0);
        processTemplateNodeUpdateDTO.setOpinionFlag(ProcessOpinionEnum.DISABLE.getValue());
        processTemplateNodeUpdateDTO.setCommitFlag(0);
        processTemplateNodeUpdateDTO.setCommitText("");
        processTemplateNodeUpdateDTO.setStorageFlag(0);
        processTemplateNodeUpdateDTO.setStorageText("");
        processTemplateNodeUpdateDTO.setCommitPrintFlag(0);
        processTemplateNodeUpdateDTO.setCommitPrintText("");
        processTemplateNodeUpdateDTO.setBackFlag(1);
        processTemplateNodeUpdateDTO.setBackType(0);
        processTemplateNodeUpdateDTO.setBackText("");
        processTemplateNodeUpdateDTO.setTransferFlag(0);
        processTemplateNodeUpdateDTO.setTransferText("");
        processTemplateNodeUpdateDTO.setEndFlag(0);
        processTemplateNodeUpdateDTO.setEndText("");
        processTemplateNodeUpdateDTO.setSignType(1);
        processTemplateNodeUpdateDTO.setCommitVerifyFlag(0);
        processTemplateNodeUpdateDTO.setCcPrintFlag(0);
    }

    private void setSaasSpecialField(String attr, Integer fieldType, XbbRefTypeEnum xbbRefTypeEnum, ProcessFieldAttrPojo processFieldAttrPojo,
                                     List<String> specialContractAttrList, List<String> specialOpportunityAttrList, PaasFormExplainEntity explainEntity,
                                     boolean workflowCorpidTag) {
        Integer distributorMark = explainEntity.getDistributorMark();
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                if (specialContractAttrList.contains(attr)
                    || Objects.equals(attr, ContractEnum.PRODUCT_TOTAL.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                } else if (Objects.equals(attr, ContractEnum.PRODUCT.getAttr()) && !workflowCorpidTag) {
                    //非工作流公司关联产品字段不能修改可见要置灰
                    processFieldAttrPojo.setMustShow(1);
                } else if (Objects.equals(attr, ContractEnum.PRODUCT.getAttr()) && workflowCorpidTag) {
                    //非工作流公司关联产品字段可以修改可见置灰
                    processFieldAttrPojo.setMustShow(0);
                }else if (Objects.equals(attr, ContractEnum.AMOUNT.getAttr())){
                    processFieldAttrPojo.setMustShow(0);
                }
                break;
            case SALES_OPPORTUNITY:
                if (specialOpportunityAttrList.contains(attr)) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case CUSTOMER_MANAGEMENT:
                if (Objects.equals(attr, CustomerManagementEnum.ADD_CONTACT.getAttr())) {
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case SUPPLIER:
                if (Objects.equals(attr, SupplierEnum.ADD_SUPPLIER_CONTACT.getAttr())) {
                    processFieldAttrPojo.setMustShow(1);
                }

                if (Objects.equals(attr, SupplierEnum.PRODUCT_LIST.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case PURCHASE:
                if (Objects.equals(attr, PurchaseEnum.PRODUCT_TOTAL.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                } else if (Objects.equals(attr, PurchaseEnum.ADD_PAYPLAN.getAttr()) || Objects.equals(attr, PurchaseEnum.ADD_PAY_SHEET.getAttr()) || Objects.equals(attr, PurchaseEnum.ADD_WRITE_OFF_PREPAY.getAttr())) {
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case PAY_SHEET:
                List<String> sheetNoneEditMustShowAttrList = PaySheetEnum.processNoneEditMustShow();
                boolean noneEditableFlag = sheetNoneEditMustShowAttrList.contains(attr);
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                    processFieldAttrPojo.setMustShow(1);
                }
                if (Objects.equals(attr, PaySheetEnum.PAY_PLAN.getAttr())) {
                    processFieldAttrPojo.setSummary(0);
                }
                break;
            case PAYMENT_SHEET:
                sheetNoneEditMustShowAttrList = PaymentSheetBaseEnum.processNoneEditMustShow(distributorMark);
                noneEditableFlag = sheetNoneEditMustShowAttrList.contains(attr);
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                    processFieldAttrPojo.setMustShow(1);
                }
                if (Objects.equals(attr, PaymentSheetEnum.PAYMENT.getAttr()) || Objects.equals(attr, PaymentSheetEnum.PAYMENT_TASK.getAttr())) {
                    processFieldAttrPojo.setSummary(0);
                }
                break;
            case INVOICE:
                if (Objects.equals(attr, InvoiceEnum.CONTRACT_ID.getAttr()) || Objects.equals(attr, InvoiceEnum.PAYMENT_ID.getAttr())|| Objects.equals(attr,InvoiceEnum.PAYMENT_SHEET_ID.getAttr()) || Objects.equals(attr,InvoiceEnum.PAYMENT_RELATIONSHIP.getAttr()) || Objects.equals(attr,InvoiceEnum.CUSTOMER_NAME.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                if(Objects.equals(attr, InvoiceEnum.PAYMENT_ID.getAttr())|| Objects.equals(attr,InvoiceEnum.PAYMENT_SHEET_ID.getAttr()) || Objects.equals(attr,InvoiceEnum.PAYMENT_RELATIONSHIP.getAttr())) {
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case PURCHASE_INVOICE:
                if (Objects.equals(attr, PurchaseInvoiceEnum.PURCHASE_ID.getAttr()) || Objects.equals(attr, PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr())|| Objects.equals(attr,PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()) || Objects.equals(attr,PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr()) || Objects.equals(attr,PurchaseInvoiceEnum.SUPPLIER_NAME.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                if(Objects.equals(attr, PurchaseInvoiceEnum.PAY_PLAN_ID.getAttr())|| Objects.equals(attr,PurchaseInvoiceEnum.PAY_SHEET_ID.getAttr()) || Objects.equals(attr,PurchaseInvoiceEnum.PAY_RELATIONSHIP.getAttr())) {
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case QUOTATION:
                if (Objects.equals(attr, QuotationEnum.PRODUCT_TOTAL.getAttr()) ||
                        Objects.equals(attr, QuotationEnum.QUOTATION_NO.getAttr()) ||
                        Objects.equals(attr, QuotationEnum.CUSTOMER_ID.getAttr()) ||
                        Objects.equals(attr, QuotationEnum.OPPORTUNITY_ID.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }else if (Objects.equals(attr, QuotationEnum.PRODUCT.getAttr()) && workflowCorpidTag) {
                    //非工作流公司关联产品字段可以修改可见置灰
                    processFieldAttrPojo.setMustShow(0);
                }else if (Objects.equals(attr, QuotationEnum.PRODUCT.getAttr()) && !workflowCorpidTag) {
                    //非工作流公司关联产品字段不能修改可见要置灰
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case REFUND:
                noneEditableFlag = Objects.equals(attr, RefundEnum.REFUND_AMOUNT.getAttr()) || Objects.equals(attr, RefundEnum.CUSTOMER_ID.getAttr()) || Objects.equals(attr, RefundEnum.CONTRACT_ID.getAttr());
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case RETURNED_PURCHASE:
                noneEditableFlag = Objects.equals(attr, ReturnedPurchaseEnum.RETURNED_PURCHASE_AMOUNT.getAttr()) || Objects.equals(attr, ReturnedPurchaseEnum.SUPPLIER_ID.getAttr()) || Objects.equals(attr, ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr());
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case OTHER_INSTOCK:
                if (Objects.equals(attr, InstockEnum.TIME.getAttr()) || Objects.equals(attr, InstockEnum.REF_ID.getAttr()) || Objects.equals(attr, InstockEnum.TYPE.getAttr())
                    || Objects.equals(attr, InstockEnum.WAREHOUSE_ID.getAttr()) || Objects.equals(attr, InstockEnum.PRODUCT.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case OTHER_OUTSTOCK:
                if (Objects.equals(attr, OutstockEnum.TYPE.getAttr()) || Objects.equals(attr, OutstockEnum.WAREHOUSE_ID.getAttr()) || Objects.equals(attr, OutstockEnum.TIME.getAttr())
                        || Objects.equals(attr, OutstockEnum.REF_ID.getAttr()) || Objects.equals(attr, OutstockEnum.PRODUCT.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case WORK_ORDER_OUTSTOCK:
                if (Objects.equals(attr, WorkOrderOutstockEnum.LINK_CUSTOMER.getAttr()) || Objects.equals(attr, WorkOrderOutstockEnum.LINK_CONTACT.getAttr())  || Objects.equals(attr, WorkOrderOutstockEnum.CUSTOMER_ADDRESS.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                } else if (Objects.equals(attr, WorkOrderOutstockEnum.CUSTOMER_PHONE.getAttr())) {
                    List<ProcessFieldAttrPojo> subExplainList = JSONObject.parseArray(JSON.toJSONString(processFieldAttrPojo.getSubForm().getItems()), ProcessFieldAttrPojo.class);
                    for (ProcessFieldAttrPojo subAttrEntity : subExplainList) {
                        subAttrEntity.setNoneEditable(1);
                        subAttrEntity.setMustShow(1);
                    }
                    processFieldAttrPojo.getSubForm().setItems(subExplainList);
                }
                break;
            case CLUE:
                if (Objects.equals(attr, ClueEnum.LAST_CONNECT_TIME.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case CONTRACT_OUTSTOCK:
                if (Objects.equals(distributorMark,DistributorMarkEnum.DISTRIBUTOR.getCode()) && (Objects.equals(attr, OrderOutStockEnum.RECEIPT_PHONE.getAttr()) || Objects.equals(attr, OrderOutStockEnum.RECEIPT_ADDRESS.getAttr()) || Objects.equals(attr, OrderOutStockEnum.SEND_PHONE.getAttr()) || Objects.equals(attr, OrderOutStockEnum.SEND_ADDRESS.getAttr()))) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case CREDIT_TEMPORARY_LIMIT:
                sheetNoneEditMustShowAttrList = CreditTemporaryLimitEnum.processNoneEditMustShow(distributorMark);
                noneEditableFlag = sheetNoneEditMustShowAttrList.contains(attr);
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                    processFieldAttrPojo.setMustShow(1);
                }
                if (Objects.equals(attr, CreditTemporaryLimitEnum.APPLY_NAME.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case CREDIT_FIXED_LIMIT:
                if (Objects.equals(attr, CreditFixedLimitEnum.APPLY_ID.getAttr())) {
                    processFieldAttrPojo.setNoneEditable(1);
                }
                break;
            case OTHER_INCOME:
                sheetNoneEditMustShowAttrList = OtherIncomeEnum.processNoneEditMustShow();
                noneEditableFlag = sheetNoneEditMustShowAttrList.contains(attr);
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case OTHER_EXPENSE:
                sheetNoneEditMustShowAttrList = OtherExpenseEnum.processNoneEditMustShow();
                noneEditableFlag = sheetNoneEditMustShowAttrList.contains(attr);
                if (noneEditableFlag) {
                    processFieldAttrPojo.setNoneEditable(1);
                    processFieldAttrPojo.setMustShow(1);
                }
                break;
            case COST_ADJUST:
                if (Objects.equals(attr, CostAdjustEnum.WAREHOUSE_ID.getAttr())) {
                    processFieldAttrPojo.setMustShow(0);
                }
                break;
            default:
                break;
        }
    }


    private void transformDynamic(PaasProcessTemplateNodeEntityExt templateNodeEntityExt, Map<String, String> userIdMap, Map<String, String> depMap, Map<String, String> roleMap) {
        List<OptionalRangeEntity> mainUserList = templateNodeEntityExt.getMainUserList();
        List<OptionalRangeEntity> ccUserList = templateNodeEntityExt.getCcUserList();
        List<OptionalRangeEntity> transferUserList = templateNodeEntityExt.getTransferUserList();

        transformDynamic(mainUserList, userIdMap, depMap, roleMap);
        transformDynamic(ccUserList, userIdMap, depMap, roleMap);
        transformDynamic(transferUserList, userIdMap, depMap, roleMap);

        templateNodeEntityExt.setMainUser(JSON.toJSONString(mainUserList));
        templateNodeEntityExt.setCcUser(JSON.toJSONString(ccUserList));
        templateNodeEntityExt.setTransferUser(JSON.toJSONString(transferUserList));
    }

    private void transformDynamic(List<OptionalRangeEntity> rangeEntityList, Map<String, String> userIdMap, Map<String, String> depMap, Map<String, String> roleMap) {
        if(Objects.nonNull(rangeEntityList) && !rangeEntityList.isEmpty()) {
            for(OptionalRangeEntity rangeEntity : rangeEntityList) {
                if(Objects.equals(OptionalRangeEnum.MANAGER.getValue(), rangeEntity.getProperty())) {
                    String levelName = DynamicManagerLevelEnum.getName(Integer.valueOf(rangeEntity.getId()));
                    rangeEntity.setProperty(OptionalRangeEnum.DYNAMIC_MANAGER.getValue());
                    rangeEntity.setName(I18nMessageUtil.getMessage(I18nStringConstant.SUBMITTER) + levelName);
                    rangeEntity.setAttr(FieldTypeEnum.CREATORID.getAlias());
                } else if (Objects.equals(OptionalRangeEnum.USER.getValue(), rangeEntity.getProperty())) {
                    if (Objects.nonNull(userIdMap.get(rangeEntity.getId()))) {
                        rangeEntity.setName(userIdMap.get(rangeEntity.getId()));
                    }
                } else if (Objects.equals(OptionalRangeEnum.DEPT.getValue(), rangeEntity.getProperty())) {
                    if (Objects.nonNull(depMap.get(rangeEntity.getId()))) {
                        rangeEntity.setName(depMap.get(rangeEntity.getId()));
                    }
                } else if (Objects.equals(OptionalRangeEnum.ROLE.getValue(), rangeEntity.getProperty())) {
                    if (Objects.nonNull(roleMap.get(rangeEntity.getId()))) {
                        rangeEntity.setName(roleMap.get(rangeEntity.getId()));
                    }
                }
            }
        }
    }


    /**
     * 归档流程
     * @param processArchiveDTO
     * @return
     * @throws XbbException
     */
    @Override
    public ProcessArchiveVO archive(ProcessArchiveDTO processArchiveDTO) throws XbbException {
        ProcessArchiveVO processArchiveVO = new ProcessArchiveVO();
        String corpId = processArchiveDTO.getCorpid();
        Long formId = processArchiveDTO.getFormId();
        String userId = processArchiveDTO.getUserId();
        String userName = processArchiveDTO.getLoginUserName();
        PaasProcessTemplateEntity paasProcessTemplateEntity = new PaasProcessTemplateEntity();

        try {
            // 获取相应的归档状态的数量
            Map<String, Object> params = BeanUtil.convertBean2Map(processArchiveDTO, true);
            params.put("isArchive", BasicConstant.TWO);
            params.put("del", DelEnum.NORMAL.getDel());
            Integer noArchive = paasProcessTemplateModel.getEntitysCount(params);
            if (noArchive == 1){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_LEAST);
            }
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("isArchive", BasicConstant.ONE);
            Integer count = paasProcessTemplateModel.getEntitysCount(params);
            // 未归档版本限制50个
            if (count>= 500){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_ARCHIVE_MAX_LIMIT);
            }
            // 修改流程版本归档状态
            paasProcessTemplateEntity.setId(processArchiveDTO.getProcessTemplateId());
            paasProcessTemplateEntity.setIsArchive(BasicConstant.ONE);
            paasProcessTemplateEntity.setCorpid(corpId);
            processTemplateModel.update(paasProcessTemplateEntity);
            BeanUtil.copyProperties(processArchiveDTO, processArchiveVO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库删除流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // 记录日志
        String formName = null;
        if (Objects.equals(paasProcessTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpId);
            if (workOrderEntity != null) {
                formName = workOrderEntity.getName();
            }
        } else {
            PaasFormEntityExt formEntity = paasFormModel.getByKey(formId, corpId);
            if (formEntity != null) {
                formName = formEntity.getName();
            }
        }
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_PROCESS_TEMPLATE), userName, formName);
        mongoLogHelp.buildLog(corpId, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                OperateTypeEnum.ARCHIVED, formId.toString(), formName, memo, processArchiveDTO.getHttpHeader());

        return processArchiveVO;
    }

    /**
     * 取消归档
     * @param processArchiveDTO
     * @return
     * @throws XbbException
     */
    @Override
    public ProcessArchiveVO cancelArchive(ProcessArchiveDTO processArchiveDTO) throws XbbException {
        ProcessArchiveVO processArchiveVO = new ProcessArchiveVO();
        String corpId = processArchiveDTO.getCorpid();
        Long formId = processArchiveDTO.getFormId();
        String userId = processArchiveDTO.getUserId();
        String userName = processArchiveDTO.getLoginUserName();
        PaasProcessTemplateEntity paasProcessTemplateEntity = new PaasProcessTemplateEntity();

        try {
            // 获取相应的归档状态的数量
            Map<String, Object> params = BeanUtil.convertBean2Map(processArchiveDTO, true);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("isArchive", BasicConstant.TWO);
            Integer count = paasProcessTemplateModel.getEntitysCount(params);
            // 归档版本限制50个
            if (count >= 50) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_MAX_LIMIT);
            }
            // 修改流程版本归档状态
            BeanUtils.copyProperties(processArchiveDTO, paasProcessTemplateEntity);
            paasProcessTemplateEntity.setId(processArchiveDTO.getProcessTemplateId());
            paasProcessTemplateEntity.setIsArchive(BasicConstant.TWO);
            processTemplateModel.update(paasProcessTemplateEntity);
            BeanUtil.copyProperties(processArchiveDTO, processArchiveVO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasProcessTemplate数据库删除流程出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        // 记录日志
        String formName = null;
        if (Objects.equals(paasProcessTemplateEntity.getBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(formId, corpId);
            if (workOrderEntity != null) {
                formName = workOrderEntity.getName();
            }
        } else {
            PaasFormEntityExt formEntity = paasFormModel.getByKey(formId, corpId);
            if (formEntity != null) {
                formName = formEntity.getName();
            }
        }
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_PROCESS_TEMPLATE), userName, formName);
        mongoLogHelp.buildLog(corpId, userId, userName, OperateModuleTypeEnum.PAAS_PROCESS_TEMPLATE,
                OperateTypeEnum.CANCEL_ARCHIVED, formId.toString(), formName, memo, processArchiveDTO.getHttpHeader());

        return processArchiveVO;
    }
}
